home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / unarced / graphics / anim / preloadanim.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  13KB  |  338 lines

  1.  
  2. /** PreLoadAnim.c ***********************************************************
  3.  *
  4.  * Load an ILBM raster image file into memory structures
  5.  * This is a modified version of ReadPict.c dated 23-Jan-86.
  6.  * 
  7.  * Modified by Gary Bonham, SPARTA, Inc.  15 Aug 1986
  8.  *
  9.  ***************************************************************************/
  10.  
  11. #define LOCAL   static
  12.  
  13. #include "intuall.h"
  14. #include "libraries/dos.h"
  15. #include "libraries/dosextens.h"
  16. #include "ilbm.h"
  17. #include "readpict.h"
  18. #include "putanim.h"
  19. #include "preloadanim.h"
  20. #include "functions.h"
  21.  
  22.  
  23. /* This example's max number of planes in a bitmap. Could use MaxAmDepth. */
  24. #define EXDepth 5
  25. #define maxColorReg (1<<EXDepth)
  26. /*#define MIN(a,b) ((a)<(b)?(a):(b))*/
  27.  
  28. #define GetANHD(context,anHdr) \
  29.    IFFReadBytes(context,(BYTE *)anHdr,(long)sizeof(AnimationHeader))
  30.  
  31. /* Define the size of a temporary buffer used in unscrambling the ILBM rows.*/
  32. #define bufSz 512
  33.  
  34. int EndFlag;
  35. struct IFFfile *IFFfileList;
  36.  
  37. /*------------ ILBM reader -----------------------------------------------*/
  38. /* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
  39.  * We allocate one of these on the stack for every LIST or FORM encountered
  40.  * in the file and use it to hold BMHD & CMAP properties. We also allocate
  41.  * an initial one for the whole file.
  42.  * We allocate a new GroupContext (and initialize it by OpenRIFF or
  43.  * OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
  44.  * just a context for reading (nested) chunks.
  45.  *
  46.  * If we were to scan the entire example file outlined below:
  47.  *    reading          proc(s)                new               new
  48.  *
  49.  * --whole file--   ReadPicture+ReadIFF   GroupContext        ILBMFrame
  50.  * CAT              ReadICat                GroupContext
  51.  *   LIST           GetLiILBM+ReadIList       GroupContext        ILBMFrame
  52.  *     PROP ILBM    GetPrILBM                   GroupContext
  53.  *       CMAP       GetCMAP
  54.  *       BMHD       GetBMHD
  55.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  56.  *       BODY       GetBODY
  57.  *     FORM ILBM    GetFoILBM                   GroupContext        ILBMFrame
  58.  *       BODY       GetBODY
  59.  *   FORM ILBM      GetFoILBM                 GroupContext        ILBMFrame
  60.  */
  61.  
  62. /* NOTE: For a small version of this program, set Fancy to 0.
  63.  * That'll compile a program that reads a single FORM ILBM in a file, which
  64.  * is what DeluxePaint produces. It'll skip all LISTs and PROPs in the input
  65.  * file. It will, however, look inside a CAT for a FORM ILBM.
  66.  * That's suitable for 90% of the uses.
  67.  *
  68.  * For a fancier version that handles LISTs and PROPs, set Fancy to 1.
  69.  * That'll compile a program that dives into a LIST, if present, to read
  70.  * the first FORM ILBM. E.g. a DeluxePrint library of images is a LIST of
  71.  * FORMs ILBM.
  72.  *
  73.  * For an even fancier version, set Fancy to 2. That'll compile a program
  74.  * that dives into non-ILBM FORMs, if present, looking for a nested FORM ILBM.
  75.  * E.g. a DeluxeVideo C.S. animated object file is a FORM ANBM containing a
  76.  * FORM ILBM for each image frame. */
  77.  
  78. /* Global access to client-provided pointers.*/
  79. LOCAL anim;
  80. extern IFFP GetLiILBM(),GetPrILBM();
  81. BYTE *SavePlanes[2];
  82.  
  83. /** GetFoANIM() *************************************************************
  84.  *
  85.  * Called via ReadPicture to handle every FORM encountered in an IFF file.
  86.  * Reads FORMs ILBM and skips all others.
  87.  * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
  88.  * finds no BODY or if it has no BMHD to decode the BODY.
  89.  *
  90.  * Once we find a BODY chunk, we'll allocate the BitMap and read the image.
  91.  *
  92.  ****************************************************************************/
  93. LOCAL BYTE bodyBuffer[bufSz];
  94. IFFP GetFoANIM(parent)
  95. GroupContext *parent;
  96. {
  97.    /*compilerBug register*/ IFFP iffp;
  98.  
  99.    GroupContext formContext;
  100.    ILBMFrame ilbmFrame;      /* only used for non-clientFrame fields.*/
  101.  
  102.    /* Handle a non-ILBM FORM. */
  103.    if (parent->subtype != ID_ILBM) {
  104.       if (parent->subtype == ID_ANIM) anim = 1;
  105.       /* Open a non-ILBM FORM and recursively scan it for ILBMs.*/
  106.       iffp = OpenRGroup(parent, &formContext);
  107.       CheckIFFP();
  108.       do {
  109.           iffp = GetF1ChunkHdr(&formContext);
  110.           if (iffp == IFF_DONE) iffp = IFF_OKAY;
  111.       } while (iffp >= IFF_OKAY);
  112.       if (iffp == END_MARK)  iffp = IFF_DONE;   /* then continue scanning the file */
  113.       CloseRGroup(&formContext);
  114.       return(iffp);
  115.    }
  116.  
  117.    ilbmFrame = *(ILBMFrame *)parent->clientFrame;
  118.    iffp = OpenRGroup(parent, &formContext);
  119.    CheckIFFP();
  120.  
  121.    if (IFFfileList->lastframe == NULL) {
  122.       IFFfileList->lastframe =
  123.               (struct FrameHD *)AllocMem((long)sizeof(struct FrameHD)
  124.                            ,(long)(MEMF_CLEAR));
  125.       IFFfileList->firstframe = IFFfileList->lastframe;
  126.       IFFfileList->lastframe->prev = NULL;
  127.    }
  128.    else {
  129.       IFFfileList->lastframe->next =
  130.               (struct FrameHD *)AllocMem((long)sizeof(struct FrameHD)
  131.                            ,(long)(MEMF_CLEAR));
  132.       IFFfileList->lastframe->next->prev = IFFfileList->lastframe;
  133.       IFFfileList->lastframe = IFFfileList->lastframe->next;
  134.    }
  135.    if (IFFfileList->lastframe == 0)
  136.       GoodBye("Not enough memory for animation");
  137.    IFFfileList->lastframe->next = NULL;
  138.    IFFfileList->lastframe->bmhd = NULL;
  139.    IFFfileList->lastframe->anhd = NULL;
  140.    IFFfileList->lastframe->camg = NULL;
  141.    IFFfileList->lastframe->nColorRegs = 0;
  142.    IFFfileList->lastframe->body = NULL;
  143.    IFFfileList->lastframe->bodylength = 0;
  144.  
  145.    do {
  146.       switch (iffp = GetFChunkHdr(&formContext)) {
  147.          case ID_ANHD: {
  148.             ilbmFrame.foundBMHD = TRUE;
  149.             IFFfileList->lastframe->anhd =
  150.                (AnimationHeader *)AllocMem((long)sizeof(AnimationHeader),0L);
  151.             if (IFFfileList->lastframe->anhd == 0) {
  152.                   puts("Not enough memory for animation...");
  153.                   puts("\n *** Animation truncated *** \n");
  154.                   iffp = IFF_DONE;
  155.                   break;
  156.             }
  157.         iffp = GetANHD(&formContext, IFFfileList->lastframe->anhd);
  158.         break;
  159.          }
  160.          case ID_BMHD: {
  161.             int hh;
  162.             ilbmFrame.foundBMHD = TRUE;
  163.             IFFfileList->lastframe->bmhd =
  164.                (BitMapHeader *)AllocMem((long)sizeof(BitMapHeader),0L);
  165.             if (IFFfileList->lastframe->bmhd == 0)
  166.                GoodBye("Not enough memory for animation");
  167.             iffp = GetBMHD(&formContext, IFFfileList->lastframe->bmhd);
  168.             if (IFFfileList->lastframe->bmhd->pageHeight <
  169.                 IFFfileList->lastframe->bmhd->h) 
  170.                     IFFfileList->lastframe->bmhd->pageHeight
  171.                       = IFFfileList->lastframe->bmhd->h;
  172.             if (IFFfileList->lastframe->bmhd->pageWidth <
  173.                 IFFfileList->lastframe->bmhd->w) 
  174.                     IFFfileList->lastframe->bmhd->pageWidth
  175.                       = IFFfileList->lastframe->bmhd->w;
  176.             hh = IFFfileList->lastframe->bmhd->nPlanes
  177.                * IFFfileList->lastframe->bmhd->pageHeight;
  178.             SavePlanes[0] = (BYTE *)AllocRaster(
  179.                  (long)IFFfileList->lastframe->bmhd->pageWidth,(long)hh);
  180.             SavePlanes[1] = (BYTE *)AllocRaster(
  181.                  (long)IFFfileList->lastframe->bmhd->pageWidth,(long)hh);
  182.             if (SavePlanes[1] == 0)
  183.                GoodBye("Not enough memory for animation bitmaps");
  184.             break;
  185.          }
  186.          case ID_CAMG: {
  187.             ilbmFrame.foundCAMG = TRUE;
  188.             IFFfileList->lastframe->camg =
  189.                (CamgChunk *)AllocMem((long)sizeof(CamgChunk),0L);
  190.             if (IFFfileList->lastframe->camg == 0)
  191.                GoodBye("Not enough memory for animation");
  192.             iffp = GetCAMG(&formContext
  193.                           ,IFFfileList->lastframe->camg);
  194.             break;
  195.          }
  196.          case ID_CMAP: {
  197.             IFFfileList->lastframe->nColorRegs
  198.                = maxColorReg;  /* we have room for this many */
  199.             iffp = GetCMAP(&formContext
  200.                           ,&IFFfileList->lastframe->cmap[0]
  201.                           ,&IFFfileList->lastframe->nColorRegs);
  202.             break;
  203.          }
  204.          case ID_DLTA: /* at this point just read in delta chunk */
  205.          case ID_BODY: {
  206.             if (!ilbmFrame.foundBMHD)  return(BAD_FORM);   /* No BMHD chunk! */
  207.             IFFfileList->lastframe->bodylength = formContext.ckHdr.ckSize;
  208.             if (IFFfileList->lastframe->bodylength) {
  209.                IFFfileList->lastframe->body = (ULONG *)AllocMem(
  210.                             (long)(IFFfileList->lastframe->bodylength),0L);
  211.                if (IFFfileList->lastframe->body == 0) {
  212.                   puts("Not enough memory for animation body...");
  213.                   puts("\n *** Animation truncated *** \n");
  214.      EndFlag = 1;
  215.                   iffp = END_MARK;
  216.                   break;
  217.                }
  218.                IFFReadBytes(&formContext,(BYTE *)IFFfileList->lastframe->body
  219.                                      ,IFFfileList->lastframe->bodylength);
  220.             }
  221.             else IFFfileList->lastframe->bodylength = 0;
  222.             break;
  223.          }
  224.          case END_MARK: {
  225.             iffp = IFF_DONE; 
  226.             break;
  227.          } /* No BODY chunk! */
  228.       }
  229.    } while (iffp >= IFF_OKAY);  /* loop if valid ID of ignored chunk or a
  230.                                * subroutine returned IFF_OKAY (no errors).*/
  231.  
  232.    if (iffp != IFF_DONE)  return(iffp);
  233.  
  234.    /* If we get this far, there were no errors. */
  235.    CloseRGroup(&formContext);
  236.    return(iffp);
  237. }
  238.  
  239. /** Notes on extending GetFoILBM ********************************************
  240.  *
  241.  * To read more kinds of chunks, just add clauses to the switch statement.
  242.  * To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
  243.  * the switch statement in GetPrILBM, too.
  244.  *
  245.  * To read a FORM type that contains a variable number of data chunks--e.g.
  246.  * a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
  247.  * an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
  248.  * case do whatever cleanup you need.
  249.  *
  250.  ****************************************************************************/
  251.  
  252. /** PreLoadAnimation() **********************************************************/
  253. IFFP PreLoadAnimation(filename, file, iFrame)
  254. char *filename;
  255. LONG file;
  256. ILBMFrame *iFrame;   /* Top level "client frame".*/
  257.  
  258. {
  259.    int i;
  260.    struct IFFfile *IFFptr;
  261.    IFFP iffp = IFF_OKAY;
  262.    anim = 0;
  263.  
  264.    iFrame->clientFrame.getList = GetLiILBM;
  265.    iFrame->clientFrame.getProp = GetPrILBM;
  266.    iFrame->clientFrame.getForm = GetFoANIM;
  267.    iFrame->clientFrame.getCat  = ReadICat ;
  268.  
  269.    /* Initialize the top-level client frame's property settings to the
  270.     * program-wide defaults. This example just records that we haven't read
  271.     * any BMHD property or CMAP color registers yet. For the color map, that
  272.     * means the default is to leave the machine's color registers alone.
  273.     * If you want to read a property like GRAB, init it here to (0, 0). */
  274.    iFrame->foundBMHD  = FALSE;
  275.    iFrame->nColorRegs = 0;
  276.  
  277.   /* Store a pointer to the client's frame in a global variable so that
  278.    * GetFoILBM can update client's frame when done.  Why do we have so
  279.    * many frames & frame pointers floating around causing confusion?
  280.    * Because IFF supports PROPs which apply to all FORMs in a LIST,
  281.    * unless a given FORM overrides some property.  
  282.    * When you write code to read several FORMs,
  283.    * it is ssential to maintain a frame at each level of the syntax
  284.    * so that the properties for the LIST don't get overwritten by any
  285.    * properties specified by individual FORMs.
  286.    * We decided it was best to put that complexity into this one-FORM example,
  287.    * so that those who need it later will have a useful starting place.
  288.    */
  289.  
  290.    IFFptr = (struct IFFfile *)AllocMem((long)sizeof(struct IFFfile)
  291.                  ,(long)MEMF_CLEAR);
  292.    IFFptr->next = IFFfileList;
  293.    IFFfileList = IFFptr;
  294.    for (i=0;i<40;i++) IFFfileList->name[i] = filename[i];
  295.    IFFfileList->firstframe = NULL;
  296.    IFFfileList->lastframe  = NULL;
  297.  
  298.    iffp = ReadIFF(file, (ClientFrame *)iFrame);
  299.    return(iffp);
  300. }
  301.  
  302.  
  303. InitPreLoadIFF()
  304. {
  305.    IFFfileList = NULL;
  306.    return(0);
  307. }
  308.  
  309. ClosePreLoadIFF()
  310. {
  311.    struct IFFfile *currentfile,*nextfile;
  312.    struct FrameHD *currentframe,*nextframe;
  313.  
  314.    currentfile = IFFfileList;
  315.    while (currentfile) {
  316.       currentframe = currentfile->firstframe;
  317.       while (currentframe) {
  318.          if (currentframe->bmhd) FreeMem(currentframe->bmhd
  319.                                  ,(long)sizeof(BitMapHeader));
  320.          if (currentframe->anhd) FreeMem(currentframe->anhd
  321.                                  ,(long)sizeof(AnimationHeader));
  322.          if (currentframe->body) {
  323.             if (currentframe->bodylength)
  324.                FreeMem(currentframe->body
  325.                                  ,(long)currentframe->bodylength);
  326.          }
  327.          nextframe = currentframe->next;
  328.          FreeMem(currentframe,(long)sizeof(struct FrameHD));
  329.          currentframe = nextframe;
  330.       }
  331.       nextfile = currentfile->next;
  332.       FreeMem(currentfile,(long)sizeof(struct IFFfile));
  333.       currentfile = nextfile;
  334.    }
  335.    IFFfileList = NULL;
  336.    return(0);
  337. }
  338.